/*
 * Copyright (c) 2011-2012 Alexander Dubu
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * o  Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 * o  Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * o  Neither the name Axil nor the names of its contributors may be used to
 *    endorse or promote products derived from this software without specific
 *    prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */
package axil.api;

/**
 * This object defined a configuration for the Axil runtime. Different
 * configurations can be in use at the same time, allowing for customization of
 * the runtime environment for different uses or users.
 *
 * <h4>Sealed versus Mutable Configurations</h4>
 * Once a context has been put into use the first time (when the first script
 * is evaluated via the script's eval() method for a given configuration), then
 * the configuration is sealed and becomes immutable. Once sealed, any attempt
 * to alter the configuration results in an exception. A new configuration
 * (a clone) can be created from any configuration, at any time, using the
 * reconfigure() method.
 * <p/>
 * This interface is not intended to be implemented by host applications. This
 * interface provides a mechanism for encapsulating the implementation. Use the
 * Axil.instance() object to access instances of this object.
 *
 * @see axil.api.Axil#configuration()
 */
public interface Configuration {
	/**
	 * Specify the maximum amount of memory that Axil is allowed to consume
	 * when running a script. This value is per thread, not for the entire
	 * Axil runtime. If a script attempts to consume more than this amount, then
	 * the script will be terminated and an exception returned to the caller
	 * indicating the defect in the script.
	 * <p/>
	 * This operation can only be performed before the configuration is put into
	 * use. Once a context has been created associated with this configuration,
	 * then the configuration is sealed (immutable). Any attempt to invoke this
	 * method after that time will result in an exception.
	 *
	 * @param bytes
	 * 	The number of bytes that are the maximum heap space Axil will consume
	 * 	when running.
	 */
	public void memory(int bytes);


	/**
	 * Specify the maximum amount of output that can be generated into the
	 * console by the script. If a script attempts to generate more than this
	 * amount, then the script will be terminated and an exception returned to
	 * the caller indicating the defect in the script. If this is in explicitly
	 * invoked, then a reasonable limit will be automatically applied.
	 * <p/>
	 * This operation can only be performed before the configuration is put into
	 * use. Once a context has been created associated with this configuration,
	 * then the configuration is sealed (immutable). Any attempt to invoke this
	 * method after that time will result in an exception.
	 *
	 * @param chars
	 * 	The number of characters that can be output. A value less than or equal
	 * 	to zero indicates that no limit is being imposed on output. Note that
	 * 	allowing unlimited output is intentionally disabling an Axil safety
	 * 	mechanism.
	 *
	 * @see Script#eval(axil.api.extend.Environment)
	 */
	public void output(int chars);

	/**
	 * Set the maximum duration that a script is allowed to execute before
	 * forcibly terminating the script. In general, long-running scripts are
	 * not an issue in Axil, and the functional nature of the execution means
	 * that the memory and output limits are typically sufficient to ensure safe
	 * operation. However, application-specific types or functions may introduce
	 * opportunities for runaway scripts that neither consume too much memory
	 * nor exceed stack limits. The standard library provided with Axil is
	 * immune to these effects. Therefore, this feature is disabled by default,
	 * allowing scripts to run for an extended period of time.
	 * <p/>
	 * This operation can only be performed before the configuration is put into
	 * use. Once a context has been created associated with this configuration,
	 * then the configuration is sealed (immutable). Any attempt to invoke this
	 * method after that time will result in an exception.
	 * <p/>
	 * Finally, note that there is significant overhead associated with
	 * enabling this feature. This feature introduces synchronization and related
	 * threading overhead to an otherwise re-entrant execution mechanism.
	 *
	 * @param milliseconds
	 * 	The maximum number of milliseconds a script is allowed to execute. A
	 * 	value of -1 is set to indicate this feature is disabled.
	 */
	public void duration(int milliseconds);


	/**
	 * Indicate that the types, constants, functions and operators defined in
	 * the given module are accessible to script compiled and executed under
	 * this context. By default, only the "core" module is available. All other
	 * modules must be explicitly specified.
	 * <p/>
	 * This operation can only be performed before the configuration is put into
	 * use. Once a context has been created associated with this configuration,
	 * then the configuration is sealed (immutable). Any attempt to invoke this
	 * method after that time will result in an exception.
	 *
	 * @param module
	 */
	public void use(String module);


	/**
	 * Put an object that is specific to the host application into this
	 * configuration. If an object already exists with that key, then that
	 * object is replaced with this one. This method is provided to allow the
	 * host application to make its own configuration visible to objects like
	 * source adapters.
	 * <p/>
	 * This operation can only be performed before the configuration is put into
	 * use. Once a context has been created associated with this configuration,
	 * then the configuration is sealed (immutable). Any attempt to invoke this
	 * method after that time will result in an exception.
	 *
	 * @param key
	 * 	The host application key, which cannot be null or empty.
	 *
	 * @param value
	 * 	The host application object, which cannot be null.
	 *
	 * @see axil.api.extend.SourceAdapter
	 */
	public void put(String key, Object value);


	/**
	 * Get an object that is specific to the host application into this
	 * configuration. If there is no object associated with that key, then an
	 * exception is thrown.
	 *
	 * @param key
	 * 	The host application key, which cannot be null or empty.
	 *
	 * @return
	 * 	Returns the value from the last put() operation for this key. The
	 * 	object returned is never null.
	 */
	public Object get(String key);


	/**
	 * Return a clone of this configuration suitable for modification. This
	 * method can be safely invoked at any time.
	 *
	 * @return
	 * 	Returns a clone of this configuration, with the clone being completely
	 * 	isolated. No modifications to the returned object have side effects
	 * 	to this object.
	 */
	public Configuration reconfigure();


	/**
	 * Get the Axil type metadata for the type defined by the given identity.
	 *
	 * @param ident
	 * 	The identity, which cannot be null or empty.
	 *
	 * @return
	 * 	Returns the type metadata, or a null if there is no such type with that
	 * 	identity.
	 */
	public AxilType type(String ident);
}
